home *** CD-ROM | disk | FTP | other *** search
/ Almathera Ten Pack 3: CDPD 3 / Almathera Ten on Ten - Disc 3: CDPD3.iso / scope / 001-025 / scopedisk3 / 68kasm / src / codegen.c < prev    next >
C/C++ Source or Header  |  1995-03-18  |  22KB  |  728 lines

  1. /*------------------------------------------------------------------*/
  2. /*                                    */
  3. /*              MC68000 Cross Assembler                */
  4. /*                                    */
  5. /*          Copyright    (c) 1985 by Brian R. Anderson            */
  6. /*                                    */
  7. /*          Object code generator - March 20,    1988            */
  8. /*                                    */
  9. /*   This program may be copied    for personal, non-commercial use    */
  10. /*   only, provided that the above copyright notice is included        */
  11. /*   on    all copies of the source code.    Copying    for any    other use   */
  12. /*   without the consent of the    author is prohibited.            */
  13. /*                                    */
  14. /*------------------------------------------------------------------*/
  15. /*                                    */
  16. /*        Originally published (in Modula-2) in            */
  17. /*        Dr.    Dobb's Journal, April, May, and June 1986.          */
  18. /*                                    */
  19. /*    AmigaDOS conversion copyright (c) 1988 by Charlie Gibbs.    */
  20. /*                                    */
  21. /*------------------------------------------------------------------*/
  22.  
  23. #include <stdio.h>
  24. #include "a68kdef.h"
  25. #include "a68kglb.h"
  26.  
  27. /* Functions */
  28. extern int  LineParts(), GetField(), Instructions(), ObjDir();
  29. extern int  GetSize(), GetInstModeSize(), GetMultReg();
  30. extern int  ReadSymTab(), GetArgs(), GetAReg(),    OpenIncl();
  31. extern long AddrBndW(),    AddrBndL(), GetValue(),    CalcValue();
  32. extern char *malloc();
  33. extern FILE *fopen();
  34.  
  35.  
  36.  
  37. GetObjectCode (dummy) int dummy;
  38. /* Determines the object code for the operation    as well    as the operands    */
  39. /* Returns each    (up to 3 fields), along    with the length    of each.     */
  40. {
  41.     int     quick;
  42.     int     ExtL;        /* Bit pattern for instruction extension word */
  43.     long templong;
  44.     char tempop[MAXLINE];
  45.     register int i, j;
  46.  
  47.     if (Dir != None)
  48.     return;                /* Directive - already done */
  49.  
  50.     if ((Label[0] != '\0') || (OpCode[0] != '\0'))
  51.     PrntAddr = TRUE;        /* Print address at least */
  52.  
  53.     if (OpCode[0] == '\0') {
  54.     MakeHunk |= PrntAddr;
  55.     return;                /* No op code, exit now    */
  56.     }
  57.     if (!Instructions (OpLoc)) {    /* Get instruction parts */
  58.     AddrAdv    = InstSize = 0;
  59.     PrntAddr = FALSE;
  60.     Dir = MacCall;            /* Assume it's a macro call */
  61.     if (InF->UPtr == 0)        /* If we're reading from a file */
  62.         InF->Pos = ftell(InFile);    /*  remember where we are */
  63.     tempop[0] = ' ';
  64.     tempop[1] = '\0';
  65.     strcat (tempop,    OpCode);    /* Prepend a blank to OpCode */
  66.     if (ReadSymTab (tempop)) {    /* Search for user macro */
  67.         AddRef (LineCount);
  68.         InFNum++;
  69.         if (--InF <    LowInF)
  70.         LowInF = InF;
  71.         MacCount++;
  72.         Heap2Space (0);        /* Check for space */
  73.         InF->UPtr =    Heap + Hunk2;    /* MACRO statement */
  74.         InF->UPtr += strlen    (InF->UPtr) + 1;  /* Skip over it */
  75.         InF->NPtr =    NextFNS;    /* New stack pointer */
  76.         InF->Line =    0;        /* Line    number in macro    */
  77.         InF->NArg =    GetArgs    ("");   /* Get arguments */
  78.         InF->MCnt =    MacCount;    /* Macro number    */
  79.         if (OuterMac == 0)
  80.         OuterMac = InFNum;    /* Outer macro */
  81.         return;
  82.     }
  83.     if (!OpenIncl (OpCode, InclList)) {
  84.         Error (OpLoc, NoCode);    /* Couldn't open file */
  85.         if (InF->UPtr == 0)    {
  86.         InFile = fopen (InF->NPtr, "r");
  87.         fseek (InFile, InF->Pos, 0);
  88.         }
  89.         return;            /* Return to outer file    */
  90.     }
  91.     InFNum++;            /* Bump    nesting    level */
  92.     if (--InF < LowInF)
  93.         LowInF = InF;
  94.     MacCount++;
  95.     Heap2Space (0);            /* Check for space */
  96.     InF->UPtr = 0;            /* Not a user macro */
  97.     InF->NPtr = NextFNS;        /* New stack pointer */
  98.     InF->Line = 0;            /* Line    number in macro    */
  99.     InF->NArg = GetArgs (OpCode);    /* Get arguments */
  100.     InF->MCnt = MacCount;        /* Macro number    */
  101.     if (OuterMac ==    0)
  102.         OuterMac = InFNum;        /* Outer macro */
  103.     return;
  104.     }
  105.  
  106.     MakeHunk = TRUE;            /* We have something for a hunk    */
  107.     AddrCnt = AddrBndW (AddrCnt);    /* It'll be word-aligned */
  108.  
  109.     if ((AdrModeA != 0)    || (AdrModeB !=    0)) {
  110.     Src.Loc    = SrcLoc;
  111.     Dest.Loc = DestLoc;
  112.     GetOperand (SrcOp, &Src, SrcPC IN AdrModeB ? 2 : 0);
  113.     GetOperand (DestOp, &Dest, EA05c IN AdrModeB ? 4 : 0);
  114.     }
  115.     if (EA05z IN AdrModeB) {        /* MOVEM */
  116.     if ((Src.Mode != MultiM) && (Dest.Mode != MultiM)) {
  117.         OpCode[4] =    '\0';           /* MOVEM of a single register */
  118.         Instructions (OpLoc);    /*  becomes a straight MOVE   */
  119.     }
  120.     }
  121.     if ((Src.Mode == Imm)        /* Immediate instructions */
  122.     && (Src.Hunk == ABSHUNK) &&    (Src.Defn <= LineCount)
  123.     &&       (((EA611 IN AdrModeB) && (Dest.Mode == DReg)    /* MOVE    */
  124.         && (Size ==    Long) && (Src.Value >= -128) &&    (Src.Value <= 127))
  125.     || ((EA05y IN AdrModeB)                /* ADD/SUB */
  126.         && (Src.Value > 0) && (Src.Value <=    8)))) {
  127.         strcat (OpCode,    "Q");   /* Make it ADDQ/SUBQ/MOVEQ */
  128.         Instructions (OpLoc);
  129.     }
  130.     else if ((Dest.Mode    == ARDir) && (Src.Mode <= 12)
  131.     && (((EA05y    | EA611) IN AdrModeB)    /* ADD,    SUB, or    MOVE */
  132.     || (OpM68C IN AdrModeA))) {    /* CMP */
  133.         strcat (OpCode, "A");       /* ADD op,An becomes ADDA etc. */
  134.         Instructions (OpLoc);
  135.     }
  136.     else if ((Src.Mode == Imm)        /* Immediate instructions */
  137.     && ((OpM68D    | OpM68C | OpM68X) IN AdrModeA)) {
  138.     strcat (OpCode,    "I");           /* ADD/AND/OR/SUB, CMP, EOR */
  139.     Instructions (OpLoc);        /* ADD #op,d becomes ADDI etc. */
  140.     }
  141.     else if ((Src.Mode == ARPost) && (Dest.Mode    == ARPost)
  142.     && (OpM68C IN AdrModeA)) {        /* CMP */
  143.     strcat (OpCode,    "M");           /* Generate CMPM if necessary */
  144.     Instructions (OpLoc);
  145.     }
  146.  
  147.  
  148.     /* ----------------    Check for missing operands. ----------------- */
  149.  
  150.     if ((AdrModeA != 0)    || (AdrModeB !=    0))
  151.     if (Src.Mode ==    Null)
  152.         Error (OpLoc+strlen(OpCode), OperErr);    /* No source */
  153.     else if    (Dest.Mode == Null)
  154.         if (((ImmMode & AdrModeB) == ImmMode)
  155.         || (TwoOpsA    IN AdrModeA)
  156.         || (TwoOpsB    IN AdrModeB))
  157.         Error (SrcLoc+strlen(SrcOp), OperErr);    /* No destination */
  158.  
  159.     /* If an immediate operand isn't absolute, it must be a long word */
  160.  
  161.     if ((Src.Mode == Imm) && (Size != Long) && (Src.Hunk != ABSHUNK))
  162.     Error (SrcLoc, RelErr);
  163.  
  164.     /* ------- Check for instructions with too many operands. ------- */
  165.     /* Some specialized    instruction routines contain their own tests. */
  166.  
  167.     if (AdrModeA == 0) {        /* Should have only one    operand    */
  168.     if ((AdrModeB == EA05e)    || (AdrModeB ==    (Size67    | EA05e))) {
  169.         if (Dest.Mode != Null)
  170.         Error (DestLoc,    OperErr);
  171. /*    } else if (AdrModeB == 0) { */    /* Shouldn't have any operands */
  172. /*        if (Src.Mode != Null)
  173.         Error (SrcLoc, OperErr);
  174.         if (Dest.Mode != Null)
  175.         Error (DestLoc,    OperErr); De-activated for now */
  176.     }
  177.     }
  178.  
  179.     /* ----------------    Decrement and Branch (DBcc) ----------------- */
  180.  
  181.     if (DecBr IN AdrModeA) {
  182.     if (Src.Mode !=    DReg)
  183.         Error (SrcLoc, ModeErr);
  184.     if (Dest.Value & 1)
  185.         Error (DestLoc, AlignErr);    /* Boundary alignment error */
  186.  
  187.     if (Dest.Hunk == CurrHunk) {
  188.         ObjSrc = Dest.Value    - AddrCnt - 2;    /* Relative branch distance */
  189.         Dest.Hunk =    ABSHUNK;        /* Displacement    is absolute */
  190.     } else
  191.         ObjSrc = 0;            /* Let the linker worry    about it */
  192.  
  193.     if ((ObjSrc > 32767) ||    (ObjSrc    < -32768))
  194.         Error (DestLoc, BraErr);    /* Too far to branch */
  195.  
  196.     AddrAdv    = 4;
  197.     nO = nS    = 2;
  198.     ObjOp =    Op | Src.Rn;
  199.     if (Dest.Hunk != CurrHunk) {    /* DBcc    to another section */
  200.         templong = AddrCnt + 2;    /* 16-bit relocatable */
  201.         PutRel (templong, Dest.Hunk, 2);
  202.     }
  203.     return;
  204.     }
  205.  
  206.     /* ------------ Branch (Bcc, including BRA and BSR)    ------------- */
  207.  
  208.     if (Brnch IN AdrModeA) {
  209.     if (Src.Value &    1)
  210.         Error (SrcLoc, AlignErr);    /* Boundary alignment error */
  211.  
  212.     if (Src.Hunk ==    CurrHunk) {
  213.         ObjSrc = Src.Value - AddrCnt - 2;    /* Relative branch distance */
  214.         Src.Hunk = ABSHUNK;            /* Displacement    is absolute */
  215.         if (DefLine2 <= LineCount)
  216.         if ((ObjSrc >= -128) &&    (ObjSrc    <= 127))
  217.             Size = Byte;    /* Short branch    if possible */
  218.         if ((Size == Byte) && (ObjSrc == 0))
  219.         Error (SrcLoc, BccSDsp0);    /* Can't do this! */
  220.     } else {
  221.         ObjSrc = 0;            /* Let the linker worry    about it */
  222.         if (Size ==    Byte)
  223.         Error (SrcLoc, BraErr);    /* No external short branches! */
  224.     }
  225.  
  226.     if (Size != Byte) {
  227.         InstSize = 4;
  228.         nS = 2;
  229.         templong = 32767;
  230.     } else {
  231.         InstSize = 2;
  232.         Op |= (ObjSrc & 0x00FF);
  233.         templong = 127;
  234.     }
  235.     if ((ObjSrc > templong)    || (ObjSrc < -templong-1))
  236.         Error (SrcLoc, BraErr);    /* Too far to branch */
  237.  
  238.     if (Dest.Mode != Null)
  239.         Error (DestLoc, OperErr);    /* No Destination operand! */
  240.  
  241.     AddrAdv    = InstSize;
  242.     ObjOp =    Op;
  243.     nO = 2;
  244.     if (Src.Hunk !=    CurrHunk) {    /* Bcc to another section */
  245.         templong = AddrCnt + 2;    /* 16-bit relocatable */
  246.         PutRel (templong, Src.Hunk,    2);
  247.     }
  248.     return;
  249.     }
  250.  
  251.     /* ------------ Check for short (16-bit) JMP or JSR    ------------- */
  252.  
  253.     if ((Op == JMP) || (Op == JSR))
  254.     if ((Size == Byte) && (Src.Mode    == AbsL))
  255.         Src.Mode = AbsW;
  256.  
  257.     /* ------------ Check for boundary alignment errors. ------------ */
  258.  
  259.     if ((Size != Byte) && (Op != LEA) && (Op !=    PEA)) {
  260.     if (Src.Value &    1)
  261.         if ((Src.Mode >= ARDisp) &&    (Src.Mode <= PCDisX))
  262.         Error (SrcLoc, AlignErr);
  263.     if (Dest.Value & 1)
  264.         if ((Dest.Mode >= ARDisp) && (Dest.Mode <= PCDisX))
  265.         Error (DestLoc,    AlignErr);
  266.     }
  267.  
  268. /*  Uses information from Instructions & GetOperand (among others)  */
  269. /*  to complete    calculation of Object Code.                */
  270. /*  Op,    AdrModeA, AdrModeB, Size, and Src & Dest records are all    */
  271. /*  Global variables imported from the SyntaxAnalyzer MODULE.        */
  272.  
  273.     ExtL = 0;
  274.     quick = FALSE;
  275.  
  276. /* Check for 5 special cases first */
  277.  
  278.     if (Op == STOP) {
  279.     if (Src.Mode !=    Imm)
  280.         Error (SrcLoc, OperErr);
  281.     if (Dest.Mode != Null)
  282.         Error (DestLoc, OperErr);
  283.     }
  284.  
  285.     if (Op == LINK) {
  286.     Op |= Src.Rn;
  287.     if (Src.Mode !=    ARDir)
  288.         Error (SrcLoc, ModeErr);
  289.     if (Dest.Mode != Imm)
  290.         Error (DestLoc, ModeErr);
  291.     else if    (Dest.Value & 1)
  292.         Error (DestLoc, AlignErr);    /* Boundary alignment error */
  293.     }
  294.  
  295.     if (Op == SWAP)
  296.     if (!(EA05f IN AdrModeB)) { /* Ignore if PEA instruction */
  297.         Op |= Src.Rn;
  298.         if (Src.Mode != DReg)
  299.         Error (SrcLoc, OperErr);
  300.         if (Dest.Mode != Null)
  301.         Error (DestLoc,    OperErr);
  302.     }
  303.  
  304.     if (Op == UNLK) {
  305.     Op |= Src.Rn;
  306.     if (Src.Mode !=    ARDir)
  307.         Error (SrcLoc, OperErr);
  308.     if (Dest.Mode != Null)
  309.         Error (DestLoc, OperErr);
  310.     }
  311.  
  312. /* Now do generalized address modes */
  313.  
  314.     if ((Ry02 IN AdrModeA) && (Rx911 IN    AdrModeA)) { /*    Two registers */
  315.     if (Op == CMPM)    {        /* Special routine for CMPM */
  316.         Op |= Src.Rn | (Dest.Rn << 9);
  317.         if (Src.Mode != ARPost)
  318.         Error (SrcLoc, ModeErr);
  319.         if (Dest.Mode != ARPost)
  320.         Error (DestLoc,    ModeErr);
  321.     } else {        /* Other two-register instructions */
  322.         Op |= Src.Rn | (Dest.Rn << 9);
  323.         if (RegMem3    IN AdrModeA) {
  324.         if (Src.Mode ==    DReg) {
  325.             if (Dest.Mode != DReg)
  326.             Error (DestLoc,    ModeErr);
  327.         } else if (Src.Mode == ARPre) {
  328.             Op |= 0x0008;
  329.             if (Dest.Mode != ARPre)
  330.             Error (DestLoc,    ModeErr);
  331.         } else
  332.             Error (SrcLoc, OperErr);
  333.         } else {
  334.         if (Src.Mode ==    ARPost)
  335.             if (Dest.Mode != ARPost)
  336.             Error (DestLoc,    ModeErr);
  337.             else
  338.             Error (SrcLoc, OperErr);
  339.         }
  340.     }
  341.     }
  342.  
  343.     if (Data911    IN AdrModeA) {        /* Data    in 9-11    (ADDQ/SUBQ) */
  344.     quick =    TRUE;
  345.     if (Src.Mode ==    Imm)
  346.         if ((Src.Value > 0)    && (Src.Value <= 8)) {
  347.         if (Src.Value <    8)    /* Data    of 8 is    coded as 000 */
  348.             Op |= Src.Value << 9;
  349.         } else
  350.         Error (SrcLoc, SizeErr);
  351.     else
  352.        Error (SrcLoc, OperErr);
  353.     }
  354.  
  355.     if (CntR911    IN AdrModeA) {    /* Only    Shift/Rotate use this */
  356.     if (Dest.Mode == DReg) {
  357.         Op = (Op & 0xF9FF) | Dest.Rn;
  358.         if (Size ==    Word) Op |= 0x0040;
  359.         if (Size ==    Long) Op |= 0x0080;
  360.         if (Src.Mode == DReg)
  361.         Op |= 0x0020 | (Src.Rn << 9);
  362.         else if (Src.Mode == Imm) {
  363.         quick =    TRUE;
  364.         /* Range Check */
  365.         if ((Src.Value > 0) && (Src.Value <= 8)) {
  366.             if (Src.Value < 8) /* Data of 8 is coded as    000 */
  367.             Op |= (Src.Value << 9);
  368.         } else
  369.             Error (SrcLoc, SizeErr);
  370.         } else
  371.         Error (SrcLoc, OperErr);
  372.     } else if (Dest.Mode ==    Null) {
  373.         Op = (Op & 0xFFE7) | 0x00C0;
  374.         EffAdr (&Src, (mea | aea));
  375.     } else
  376.         Error (SrcLoc, OperErr);
  377.     }
  378.  
  379.     if (Data03 IN AdrModeA) {        /* TRAP    Vector in 0-3 */
  380.     quick =    TRUE;
  381.     if (Src.Mode ==    Imm)
  382.         if ((Src.Value >= 0) && (Src.Value < 16))
  383.         Op |= Src.Value;
  384.         else
  385.         Error (SrcLoc, SizeErr);
  386.     else
  387.         Error (SrcLoc, OperErr);
  388.  
  389.     if (Dest.Mode != Null)
  390.         Error (DestLoc, OperErr);
  391.     }
  392.  
  393.     if (Data07 IN AdrModeA) {        /* Data    in 0-7 (MOVEQ) */
  394.     quick =    TRUE;
  395.     Op |= (Src.Value & 0x00FFL) | (Dest.Rn << 9);
  396.     if (Src.Mode !=    Imm)
  397.         Error (SrcLoc, ModeErr);
  398.     else if    (Dest.Mode != DReg)
  399.         Error (DestLoc, ModeErr);
  400.     else if    ((Src.Value < -128) || (Src.Value > 127))
  401.         Error (SrcLoc, SizeErr);
  402.     }
  403.  
  404.     if (OpM68D IN AdrModeA) {    /* DReg    in 6-8 (ADD/AND/OR/SUB)    */
  405.     if (Dest.Mode == DReg) {
  406.         Op |= (Dest.Rn << 9);
  407.         if ((Src.Mode == ARDir) && (Size ==    Byte))
  408.         Error (SrcLoc, SizeErr);
  409.     } else    /* Assume Src.Mode = DReg -- Error trapped elsewhere */
  410.         Op |= (Src.Rn << 9)    | 0x0100;
  411.  
  412.     if (Size == Word) Op |=    0x0040;
  413.     if (Size == Long) Op |=    0x0080;
  414.     }
  415.  
  416.     if (OpM68A IN AdrModeA) {    /* AReg    in 6-8 (ADDA/CMPA/SUBA)    */
  417.     if (Dest.Mode == ARDir)
  418.         Op |= (Dest.Rn << 9);
  419.     else
  420.         Error (DestLoc, ModeErr);
  421.  
  422.     if (Size == Byte) Error    (OpLoc+5, SizeErr);
  423.     if (Size == Word) Op |=    0x00C0;
  424.     if (Size == Long) Op |=    0x01C0;
  425.     }
  426.  
  427.     if (OpM68C IN AdrModeA) {        /* CMP (Compare) */
  428.     if (Dest.Mode == DReg)
  429.         Op |= (Dest.Rn << 9);
  430.     else
  431.         Error (DestLoc, ModeErr);
  432.  
  433.     if (Size == Byte) {
  434.         if (Src.Mode == ARDir)
  435.         Error (OpLoc+4,    SizeErr);
  436.     }
  437.     if (Size == Word) Op |=    0x0040;
  438.     if (Size == Long) Op |=    0x0080;
  439.     }
  440.  
  441.     if (OpM68X IN AdrModeA) {        /* EOR (Exclusive or) */
  442.     if (Src.Mode ==    DReg)
  443.         Op |= (Src.Rn << 9);
  444.     else
  445.         Error (SrcLoc, ModeErr);
  446.  
  447.     if (Size == Byte) Op |=    0x0100;
  448.     if (Size == Word) Op |=    0x0140;
  449.     if (Size == Long) Op |=    0x0180;
  450.     }
  451.  
  452.     if (OpM68S IN AdrModeA) {        /* EXT (Sign extension)    */
  453.     if (Src.Mode ==    DReg)
  454.         Op |= Src.Rn;
  455.     else
  456.         Error (SrcLoc, ModeErr);
  457.  
  458.     if (Dest.Mode != Null)
  459.         Error (DestLoc, OperErr);
  460.  
  461.     if (Size == Byte) Error    (OpLoc+4, SizeErr);
  462.     if (Size == Word) Op |=    0x0080;
  463.     if (Size == Long) Op |=    0x00C0;
  464.     }
  465.  
  466.     if (OpM68R IN AdrModeA) {        /* MOVEP (Register/memory) */
  467.     if ((Src.Mode == DReg) && (Dest.Mode ==    ARDisp)) {
  468.         if (Size ==    Byte) Error (OpLoc+6, SizeErr);
  469.         if (Size ==    Word) Op |= 0x0180;
  470.         if (Size ==    Long) Op |= 0x01C0;
  471.         Op |= (Src.Rn << 9)    | Dest.Rn;
  472.     } else if ((Src.Mode ==    ARDisp)    && (Dest.Mode == DReg))    {
  473.         if (Size ==    Byte) Error (OpLoc+6, SizeErr);
  474.         if (Size ==    Word) Op |= 0x0100;
  475.         if (Size ==    Long) Op |= 0x0140;
  476.         Op |= Src.Rn | (Dest.Rn << 9);
  477.     } else
  478.         Error (SrcLoc, ModeErr);
  479.     }
  480.  
  481.     if (OpM37 IN AdrModeA) {        /* EXG (Exchange registers) */
  482.     if ((Src.Mode == DReg) && (Dest.Mode ==    DReg))
  483.         Op |= 0x0040 | (Src.Rn << 9) | Dest.Rn;
  484.     else if    ((Src.Mode == ARDir) &&    (Dest.Mode == ARDir))
  485.         Op |= 0x0048 | (Src.Rn << 9) | Dest.Rn;
  486.     else if    ((Src.Mode == ARDir) &&    (Dest.Mode == DReg))
  487.         Op |= 0x0088 | (Dest.Rn << 9) | Src.Rn;
  488.     else if    ((Src.Mode == DReg) && (Dest.Mode == ARDir))
  489.         Op |= 0x0088 | (Src.Rn << 9) | Dest.Rn;
  490.     else
  491.         Error (SrcLoc, ModeErr);
  492.     }
  493.  
  494.     if (Bit811 IN AdrModeB) {    /* Bit operations using    bits 8-11 */
  495.     if (Src.Mode ==    DReg)
  496.         Op |= 0x0100 | (Src.Rn << 9);
  497.     else if    (Src.Mode == Imm)
  498.         Op |= 0x0800;
  499.     else
  500.         Error (SrcLoc, ModeErr);
  501.     }
  502.  
  503.     if (Size67 IN AdrModeB) {        /* Size    in bits    6-7 */
  504.      /*    if (Size == Byte) ; No action -- bits are already 0 */
  505.     if (Size == Word) Op |=    0x0040;
  506.     if (Size == Long) Op |=    0x0080;
  507.     }
  508.  
  509.     if (Size6 IN AdrModeB) {        /* Size    in bit 6 (MOVEM) */
  510.     if (Size == Byte) Error    (OpLoc+6, SizeErr);
  511.      /*    if (Size == Word) ; No Action -- bit is    already    0 */
  512.     if (Size == Long) Op |=    0x0040;
  513.     }
  514.  
  515.     if (Sz1213A    IN AdrModeB) {        /* Size    in 12-13 (MOVE)    */
  516.     if (Size == Byte) Op |=    0x1000;
  517.     if (Size == Word) Op |=    0x3000;
  518.     if (Size == Long) Op |=    0x2000;
  519.     }
  520.  
  521.     if (Sz1213 IN AdrModeB) {        /* Size    in 12-13 (MOVEA) */
  522.     Op |= (Dest.Rn << 9);
  523.     if (Size == Byte) Error    (OpLoc+6, SizeErr);
  524.     if (Size == Word) Op |=    0x3000;
  525.     if (Size == Long) Op |=    0x2000;
  526.     }
  527.  
  528.     if (EA05a IN AdrModeB)        /* Effective address - all */
  529.        if ((Dest.Mode == DReg) || (Dest.Mode ==    ARDir))
  530.        EffAdr (&Src, ea);
  531.        else
  532.        Error (DestLoc, ModeErr);
  533.  
  534.     if (EA05b IN AdrModeB)    /* Eff.    Addr. -    all except ARDir */
  535.     if (Dest.Mode == DReg) {
  536.        EffAdr (&Src, dea);
  537.        Op |= (Dest.Rn << 9);
  538.     } else
  539.         Error (DestLoc, ModeErr);
  540.  
  541.     if (EA05c IN AdrModeB)    /* BTST    */
  542.     EffAdr (&Dest, 0x0802);    /* All but ARDir/Imm */
  543.  
  544.     if (EA05d IN AdrModeB) {    /* All but PC relative & immediate */
  545.     EffAdr (&Dest, aea);
  546.     if ((Dest.Mode == ARDir) && (Size == Byte))
  547.         Error (OpLoc+5, SizeErr);
  548.     }
  549.  
  550.     if (EA05e IN AdrModeB) {    /* All but ARDir, PC relative, Imm */
  551.     if (Dest.Mode == Null)
  552.         EffAdr (&Src, (dea | aea));
  553.     else if    ((Src.Mode == Imm) || (Src.Mode    == DReg))
  554.         EffAdr (&Dest, (dea    | aea));
  555.     else
  556.         Error (SrcLoc, ModeErr);
  557.     }
  558.  
  559.     if (EA05f IN AdrModeB) {    /* JMP,    JSR, LEA, and PEA */
  560.     EffAdr (&Src, cea);
  561.     if (Rx911 IN AdrModeA)
  562.         if (Dest.Mode == ARDir)
  563.         Op |= (Dest.Rn << 9);        /* Address Reg. for    LEA */
  564.         else
  565.         Error (DestLoc,    ModeErr);   /* Must load Address Reg. */
  566.     else
  567.         if (Dest.Mode != Null)
  568.         Error (DestLoc,    OperErr);   /* No Dest.    unless LEA */
  569.     }
  570.  
  571.     if (EA05x IN AdrModeB) {        /* AND and OR */
  572.     if (Dest.Mode == DReg)
  573.         EffAdr (&Src, dea);
  574.     else if    (Src.Mode == DReg)
  575.         EffAdr (&Dest, mea | aea);
  576.     else
  577.         Error (SrcLoc, OperErr);
  578.     }
  579.  
  580.     if (EA05y IN AdrModeB) {        /* ADD and SUB */
  581.     if (Dest.Mode == DReg) {
  582.         EffAdr (&Src, ea);
  583.         if ((Src.Mode == ARDir) && (Size ==    Byte))
  584.            Error (OpLoc+4, SizeErr);
  585.     }
  586.     else if    (Src.Mode == DReg)
  587.         EffAdr (&Dest, (mea    | aea));
  588.     else
  589.         Error (SrcLoc, ModeErr);
  590.     }
  591.  
  592.     if (EA05z IN AdrModeB) {        /* MOVEM */
  593.     i = FALSE;                /* ExtL    flip indicator */
  594.     if (Src.Mode ==    MultiM)    {
  595.         EffAdr (&Dest, (mea    | aea |    0x0008));
  596.         if ((ExtL =    Src.Value) == 0)
  597.         ExtL = GetMultReg (SrcOp, (Dest.Mode ==    ARPre),    SrcLoc);
  598.         else
  599.         i = (Dest.Mode == ARPre);    /* Already have    mask */
  600.     } else if (Dest.Mode ==    MultiM)    {
  601.         Op |= 0x0400;            /* Set direction */
  602.         EffAdr (&Src, (mea | 0x0810));
  603.         if ((ExtL =    Dest.Value) == 0)
  604.         ExtL = GetMultReg (DestOp, (Src.Mode ==    ARPre),    DestLoc);
  605.         else
  606.         i = (Src.Mode == ARPre);
  607.     } else
  608.         Error (SrcLoc, OperErr);
  609.     if (i) {                /* Flip    ExtL */
  610.         j =    0;
  611.         for    (i = 0;    i < 8; i++)
  612.         j |= (ExtL & (1<<i)) <<    (15-i*2);
  613.         for    (i = 8;    i < 16;    i++)
  614.         j |= (ExtL & (1<<i)) >>    (i*2-15);
  615.         ExtL = j;
  616.     }
  617.     nO += 2;       /* extension is part of OpCode */
  618.     InstSize += 2;
  619.     }
  620.  
  621.     if (EA611 IN AdrModeB) {    /* Eff.    Addr. in 6-11 (MOVE) */
  622.     if (Dest.Mode == CCR) {            /* MOVE    to CCR */
  623.         Op = 0x44C0;
  624.         EffAdr (&Src, dea);
  625.     } else if (Dest.Mode ==    SR) {        /* MOVE    to SR */
  626.         Op = 0x46C0;
  627.         EffAdr (&Src, dea);
  628.     } else if (Src.Mode == SR) {        /* MOVE    from SR    */
  629.         Op = 0x40C0;
  630.         EffAdr (&Dest, dea | aea);
  631.     } else if (Dest.Mode ==    USP) {        /* MOVE    to USP */
  632.         Op = 0x4E60;
  633.         if (Src.Mode == ARDir)
  634.         Op |= Src.Rn;
  635.         else
  636.         Error (SrcLoc, ModeErr);
  637.     } else if (Src.Mode == USP) {        /* MOVE    from USP */
  638.         Op = 0x4E68;
  639.         if (Dest.Mode == ARDir)
  640.         Op |= Dest.Rn;
  641.         else
  642.         Error (DestLoc,    ModeErr);
  643.     } else {            /* General MOVE    instruction */
  644.         EffAdr (&Src, (ea |    xxx));
  645.         if ((Size == Byte) && (Src.Mode == ARDir))
  646.         Error (SrcLoc, SizeErr);
  647.         if (Src.Mode > 12)
  648.         Error (SrcLoc, ModeErr);
  649.         if (((1<<(Dest.Mode-1)) IN (dea|aea)) || (Dest.Mode>12))
  650.         Error (DestLoc,    ModeErr);
  651.         else if (Dest.Mode < 8) /* Register    direct or indirect */
  652.         Op |= ((Dest.Mode - 1) << 6) | (Dest.Rn    << 9);
  653.         else        /* Absolute, PC relative, or immediate */
  654.         Op |= 0x01C0 | ((Dest.Mode - 8)    << 9);
  655.         OperExt (&Dest);        /* Set up extension word */
  656.     }
  657.     }
  658.  
  659.     if ((Dest.Mode == CCR) && (Src.Mode    == Imm)) {
  660.     if ((Size67 IN AdrModeB)
  661.     && (EA05e IN AdrModeB)
  662.     && (Exten IN AdrModeB))
  663.         if (0x0400 IN Op)     /* not    ANDI/EORI/ORI */
  664.         Error (DestLoc,    ModeErr);
  665.         else
  666.         Op = (Op & 0xFF00) | 0x003C;
  667.     }
  668.  
  669.     if ((Dest.Mode == SR) && (Src.Mode == Imm))    {
  670.     if ((Size67 IN AdrModeB)
  671.     && (EA05e IN AdrModeB)
  672.     && (Exten IN AdrModeB))
  673.         if (0x0400 IN Op)     /* not    ANDI/EORI/ORI */
  674.         Error (DestLoc,    ModeErr);
  675.         else
  676.         Op = (Op & 0xFF00) | 0x007C;
  677.     }
  678.  
  679.     ObjOp = Op;
  680.     InstSize +=    2;
  681.     nO += 2;
  682.     if (nO > 2)    {
  683.     templong = ExtL;            /* Add extension word */
  684.     ObjOp =    (ObjOp << 16) |    (templong & 0x0000FFFFL);
  685.     }
  686.     if ((AdrModeA != 0)    || (AdrModeB !=    0)) {
  687.     InstSize += (nS    = GetInstModeSize (Src.Mode));
  688.     ObjSrc = Src.Value;
  689.     InstSize += (nD    = GetInstModeSize (Dest.Mode));
  690.     ObjDest    = Dest.Value;
  691.     }
  692.     if (quick) {
  693.     InstSize -= nS;        /* Source operand is in    Op */
  694.     nS = 0;
  695.     }
  696.  
  697.     if ((nS != 0) && (Src.Hunk != ABSHUNK)) {    /* SrcOp relocatable */
  698.     if ((Src.Mode == AbsL)
  699.     || (Src.Mode ==    AbsW)
  700.     || (Src.Mode ==    ARDisp)
  701.     || (Src.Mode ==    PCDisp)
  702.     || (Src.Mode ==    Imm)) {
  703.         templong = AddrCnt + nO;    /* 32- or 16-bit relocatable */
  704.         PutRel (templong, Src.Hunk,    nS);
  705.     }
  706.     if ((Src.Mode==ARDisX) || (Src.Mode==PCDisX)) {
  707.         templong = AddrCnt + nO + 1;    /* 8-bit relocatable */
  708.         PutRel (templong, Src.Hunk,    1);
  709.     }
  710.     }
  711.     if ((nD != 0) && (Dest.Hunk    != ABSHUNK)) {    /* DestOp relocatable */
  712.     if ((Dest.Mode == AbsL)
  713.     || (Dest.Mode == AbsW)
  714.     || (Dest.Mode == ARDisp)
  715.     || (Dest.Mode == PCDisp)
  716.     || (Dest.Mode == Imm)) {
  717.         templong = AddrCnt + nO + nS;    /* 32- or 16-bit relocatable */
  718.         PutRel (templong, Dest.Hunk, nD);
  719.     }
  720.     if ((Dest.Mode==ARDisX)    || (Dest.Mode==PCDisX))    {
  721.         templong = AddrCnt + nO + nS + 1;    /* 8-bit relocatable */
  722.         PutRel (templong, Dest.Hunk, 1);
  723.     }
  724.     }
  725.  
  726.     AddrAdv = InstSize;
  727. }
  728.